package org.zhangsh.nio;

import org.zhangsh.socket.HostInfo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;

/**
 * </p>
 *
 * @author zhangsh
 * @version 1.0.0
 * @since 2019-04-26
 */
public class NioTimerClient {

    public static void main(String[] args) throws IOException {

        // 创建客户端channel
        SocketChannel socketChannel = SocketChannel.open();
        socketChannel.configureBlocking(false);

        // 创建多路复用器
        Selector selector = Selector.open();

        // 开始连接服务器，这里是TCP三次握手
        boolean result = socketChannel.connect(new InetSocketAddress(HostInfo.HOST_NAME, HostInfo.HOST_PORT));
        // 如果连接上服务端，那就往多路复用器上注册read事件
        if(result){
            socketChannel.register(selector, SelectionKey.OP_READ);
            // 客户端请求数据
            doWrite(socketChannel);
        }else{
            // 没有连接，说明三次握手还没完成
            socketChannel.register(selector, SelectionKey.OP_CONNECT);
        }

        boolean stop = false;
        // 多路复用器开始循环
        while(!stop){
            // 不断轮询获取准备就绪的channel
            selector.select();

            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while(iterator.hasNext()){
                SelectionKey key = iterator.next();
                iterator.remove();

                // 判断其合法性
                if(!key.isValid()){
                    return;
                }

                // 根据不同的事件，采取不同的操作
                if(key.isConnectable()){
                    // 通过key获取绑定的channel
                    SocketChannel channel = (SocketChannel) key.channel();
                    // 完成连接
                    if(channel.finishConnect()){
                        channel.register(selector, SelectionKey.OP_READ);
                        // xie
                        doWrite(channel);
                    }else{
                        // 连接失败
                        System.exit(1);
                    }
                }

                // 服务器响应
                if(key.isReadable()){
                    // 通过key获取绑定的channel
                    SocketChannel channel = (SocketChannel) key.channel();

                    // 接收数据
                    ByteBuffer data = ByteBuffer.allocate(30);
                    channel.read(data);
                    data.flip();
                    byte[] bytes = new byte[data.remaining()];
                    data.get(bytes);
                    System.out.println("服务器的响应是："+new String(bytes,"UTF-8"));
                }

            }
        }


    }

    private static void doWrite(SocketChannel channel) throws IOException {

        ByteBuffer data = ByteBuffer.allocate(30);
        String str = "I am client";

        data.put(str.getBytes());
        data.flip();

        channel.write(data);
        if(!data.hasRemaining()){
            System.out.println("发送成功");
        }


    }
}
